cmake_minimum_required(VERSION 3.10)
project(STM32F1_Template_HAL_FreeRTOS C ASM)

# 设置目标MCU
set(MCU_FAMILY STM32F1xx)
set(MCU_MODEL STM32F103ZE)
set(CPU_CORE cortex-m3)

# 设置工具链
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_SIZE arm-none-eabi-size)

# 编译选项
add_compile_options(
    -mcpu=${CPU_CORE} 
    -mthumb 
    -mthumb-interwork 
    -ffunction-sections 
    -fdata-sections 
    -fno-common 
    -fmessage-length=0 
    -Wall 
    -Wextra 
    -Os
)

# 定义宏
add_definitions(
    -D${MCU_MODEL} 
    -DUSE_HAL_DRIVER 
    -DFREERTOS_USE_HEAP_4
)

# 包含目录
include_directories(
    User 
    HAL/Inc 
    HAL/Inc/Legacy 
    FreeRTOS/Include 
    FreeRTOS/Port/GCC/ARM_CM3 
    FatFs
    Libraries/CMSIS/Device/Include
    Libraries/CMSIS/Include
)

# 源文件
file(GLOB_RECURSE SOURCES 
    "HAL/Src/*.c" 
    "FatFs/*.c" 
    "User/*.c"
)

# 添加FreeRTOS核心文件（排除端口目录）
file(GLOB_RECURSE FREERTOS_CORE_SOURCES 
    "FreeRTOS/*.c"
)
list(FILTER FREERTOS_CORE_SOURCES EXCLUDE REGEX ".*/Port/.*")
list(APPEND SOURCES ${FREERTOS_CORE_SOURCES})

# 添加FreeRTOS ARM_CM3端口文件
file(GLOB FREERTOS_PORT_SOURCES 
    "FreeRTOS/Port/GCC/ARM_CM3/*.c"
)
list(APPEND SOURCES ${FREERTOS_PORT_SOURCES})

# 添加启动文件
set(STARTUP_FILE Libraries/CMSIS/Device/Source/arm/startup_stm32f103xe.s)
list(APPEND SOURCES ${STARTUP_FILE})

# 创建可执行文件
add_executable(${PROJECT_NAME}.elf ${SOURCES})

# 链接选项
target_link_options(${PROJECT_NAME}.elf PRIVATE
    -T${CMAKE_SOURCE_DIR}/STM32F103ZE_FLASH.ld
    -mcpu=${CPU_CORE}
    -mthumb
    -mthumb-interwork
    -Wl,--gc-sections
    -Wl,-Map=${PROJECT_NAME}.map
)

# 生成hex和bin文件
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
    COMMAND ${CMAKE_SIZE} ${PROJECT_NAME}.elf
)

# 生成链接脚本
file(WRITE ${CMAKE_SOURCE_DIR}/STM32F103ZE_FLASH.ld "
MEMORY
{
    FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
    RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 64K
}

SECTIONS
{
    .text :
    {
        KEEP(*(.isr_vector))
        *(.text)
        *(.text*)
        *(.rodata)
        *(.rodata*)
        . = ALIGN(4);
        _etext = .;
    } >FLASH

    .data :
    {
        . = ALIGN(4);
        _sdata = .;
        *(.data)
        *(.data*)
        . = ALIGN(4);
        _edata = .;
    } >RAM AT>FLASH

    .bss :
    {
        . = ALIGN(4);
        _sbss = .;
        *(.bss)
        *(.bss*)
        . = ALIGN(4);
        _ebss = .;
    } >RAM
}
")